# -*- coding: utf-8 -*-

from rest_framework.decorators import action
from urllib.parse import quote
from django.db import transaction
from django.http import HttpResponse
from openpyxl import Workbook
from openpyxl.utils import get_column_letter
from openpyxl.worksheet.table import Table
from rest_framework.request import Request
from core.request import get_verbose_name
from core.response import JsonResponse
from import_export import resources
from tablib import Dataset
from pathlib import Path
from reversion.models import Version


class HistoryModelMixin:
    """
    Retrieve a model instance.
    """

    @action(detail=True, methods=["GET"])
    def history(self, request, *args, **kwargs):
        instance = self.get_object()
        versions = Version.objects.get_for_object(instance).reverse()
        queryset = list(map(lambda x: x._object_version.object, versions))
        data = self.get_serializer(queryset, many=True, request=self.request).data
        return JsonResponse(data=data, msg="获取成功")


class ImportSerializerMixin:
    """
    自定义导出模板、导入功能
    """

    import_resources = None

    @transaction.atomic  # Django 事务,防止出错
    @action(detail=False, methods=["GET", "POST"], url_path="import")
    def import_data(self, request: Request, *args, **kwargs):
        """
        导入模板
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        if request.method == "GET":
            # 示例数据
            queryset = self.filter_queryset(self.get_queryset())
            # 导出excel 表
            response = HttpResponse(content_type="application/msexcel")
            response["Access-Control-Expose-Headers"] = f"Content-Disposition"
            response["Content-Disposition"] = (
                f'attachment;filename={quote(str(f"导入{get_verbose_name(queryset)}模板.xlsx"))}'
            )
            wb = Workbook()
            ws = wb.active
            row = get_column_letter(len(self.import_field_dict) + 1)
            column = 10
            ws.append(["序号", *self.import_field_dict.values()])
            tab = Table(displayName="Table1", ref=f"A1:{row}{column}")  # 名称管理器
            ws.add_table(tab)
            wb.save(response)
            return response

        override = True if (request.query_params.get("override") == "true") else False

        # 从excel中组织对应的数据结构，然后使用序列化器保存
        dataset = Dataset()
        import_file = request.FILES["file"]
        queryset = self.filter_queryset(self.get_queryset())
        import_resources = (
            self.import_resources
            if self.import_resources
            else resources.modelresource_factory(model=queryset.model)
        )
        import_resources._meta.skip_unchanged = override
        file_format = Path(import_file.name).suffix.lstrip(".")
        if file_format == "csv":
            dataset.load(
                import_file.read().decode("utf-8").replace("\t", ","), format="csv"
            )
        else:
            dataset.load(import_file.read())
        if import_resources.auto_import_headers:
            dataset.headers = import_resources().set_import_headers(dataset.headers)
        import_resources.user = request.user
        result = import_resources().import_data(
            dataset, dry_run=True, raise_errors=True
        )
        if not result.has_errors():
            import_resources().import_data(dataset, dry_run=False)
            return JsonResponse(msg=f"导入成功！")

        else:
            return JsonResponse(msg=f"导入失败！")


class ExportSerializerMixin:
    """
    自定义导出功能
    """

    export_resources = None

    @action(detail=False, methods=["POST"], url_path="export")
    def export_data(self, request: Request, *args, **kwargs):
        """
        导出功能
        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        queryset = self.filter_queryset(
            self.get_queryset().filter(id__in=request.data["ids"].split(","))
        )
        export_resources = (
            self.export_resources
            if self.export_resources
            else resources.modelresource_factory(model=queryset.model)
        )
        # 默认导出所有包含的字段信息，导出字段筛选功能预留
        kwargs["export_fields"] = export_resources.fields
        dataset = export_resources().export(queryset, **kwargs)
        file_name = f'{quote(str(f"导出{get_verbose_name(queryset)}"))}'
        file_format = request.data.get("format")
        if file_format == "json":
            return self.export_to_json(dataset, file_name)
        elif file_format == "xlsx":
            return self.export_to_xlsx(dataset, file_name)
        elif file_format == "xls":
            return self.export_to_xls(dataset, file_name)
        elif file_format == "csv":
            return self.export_to_csv(dataset, file_name)

    # 导出到CSV视图

    def export_to_csv(self, dataset, file_name):
        response = HttpResponse(
            dataset.csv, content_type="text/csv", charset="utf-8-sig"
        )
        response["Content-Disposition"] = f"attachment;"
        return response

    # 导出到json视图
    def export_to_json(self, dataset, file_name):
        response = HttpResponse(dataset.json, content_type="application/json")
        response["Content-Disposition"] = f"attachment;"
        return response

    # 导出到XLS视图
    def export_to_xls(self, dataset, file_name):
        response = HttpResponse(dataset.xls, content_type="application/vnd.ms-excel")
        response["Content-Disposition"] = f"attachment;"
        return response

    # 导出到XLSX视图
    def export_to_xlsx(self, dataset, file_name):
        response = HttpResponse(dataset.xlsx, content_type="application/msexcel")
        response["Content-Disposition"] = f"attachment;"
        return response
